package com.nudge.portlet;

import com.nudge.portlet.api.ActionType;
import com.nudge.portlet.api.GranularityType;
import com.nudge.portlet.api.NudgeAlert;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: Fred
 * Date: 15/07/11
 * Time: 11:14
 * To change this template use File | Settings | File Templates.
 */
public class ProcessNudgeInteraction {


    /**
     * Class logger.
     */
    private static final Logger LOG = LoggerFactory.getLogger(ProcessNudgeInteraction.class);


    /**
     * URL to connect the nudge server.
     */
    private static final String URL_NUDGE_API = "https://www.nudge.org/api/";

    HttpClient httpClient = new HttpClient();


    protected static BufferedReader callNudgeServer() {

        List<NudgeData> nudgeDataList = new ArrayList<NudgeData>();

        // TODO verify if the parameters are not incorrect

        /*
        String applicationCode = propertiesMap.get("applicationCode");

        String nudgeUser = propertiesMap.get("login");
        String nudgePwd = propertiesMap.get("password");


        PostMethod method = new PostMethod(URL_NUDGE_API + applicationCode + "/measures?"
                + "start=" + startTimestamp
                + "&end=" + endTimestamp
                + "&granularity=" + granularityType.getValue());
        // add parameter from the properties file
        method.addParameter("nudge_username", nudgeUser);
        method.addParameter("nudge_password", nudgePwd);

        HttpClient req = new HttpClient();

            // request the nudge server
            // req.executeMethod(method);

            // TODO add a test for the statusCode != 200
            LOG.debug("Nudge request statusCode={}", method.getStatusCode());
            BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));


        return reader;
            */
        return null;


    }


    /**
     * Collects the data from the nudge server with the arguments as filters.
     *
     * @param propertiesMap
     * @param startTimestamp
     * @param endTimestamp
     * @param server
     * @param segment
     * @param granularityType the granularity desired
     * @return a nudgeData list that contains all the samples data of the monitored application
     * @throws java.io.IOException
     */
    public List<NudgeData> collectApplicationData(final Map<String, Object> propertiesMap, final long startTimestamp, final long endTimestamp, final String server, final String segment, final GranularityType granularityType) throws IOException {

        // TODO verify if the parameters are not incorrect

        // prepare the request
        PostMethod postMethod = (PostMethod) constructHttpMethod(propertiesMap, ActionType.TRANSACTION_MEASURES);

        // request nudge server
        BufferedReader reader = null;
        try {
            reader = requestNudge(postMethod);
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        List<NudgeData> nudgeDataList = new ArrayList<NudgeData>();
        if (reader != null) {
            MapNudgeData mapNudgeData = new MapNudgeData();
            for (String data = reader.readLine(); data != null; data = reader.readLine()) {
                LOG.debug(data);

                // we skip the first line, this is the header line
                if (data.startsWith("Date")) {
                    continue;
                }
                nudgeDataList.add(mapNudgeData.createNudgeData(data));
            }
        }

        return nudgeDataList;

    }

    // TODO rename propertiesMap
    // TODO refactoring the calls to the nudgeServer with other collect method
    protected List<NudgeAlert> collectAlert(final Map<String, String> propertiesMap, final long startTimestamp, final long endTimestamp) {

        List<NudgeData> nudgeDataList = new ArrayList<NudgeData>();

        // TODO verify if the parameters are not incorrect

        String applicationCode = propertiesMap.get("applicationCode");
        String nudgeUser = propertiesMap.get("login");
        String nudgePwd = propertiesMap.get("password");


        PostMethod method = new PostMethod(URL_NUDGE_API + applicationCode + "/alerts?"
                + "start=" + startTimestamp
                + "&end=" + endTimestamp);
        // add parameter from the properties file
        method.addParameter("nudge_username", nudgeUser);
        method.addParameter("nudge_password", nudgePwd);


        try {
            // request the nudge server
            //req.executeMethod(method);

            // TODO add a test for the statusCode != 200
            LOG.debug("Nudge request statusCode={}", method.getStatusCode());
            BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
            LOG.debug("### Body=\n");

            // collects all the samples
            for (String data = reader.readLine(); data != null; data = reader.readLine()) {
                LOG.debug(data);

                // we skip the first line, this is the header line
                if (data.startsWith("Date")) {
                    continue;
                }
            }

        } catch (Exception e) {
            LOG.error("ERROR ", e);
        }

        return null;
    }


    /**
     * Construct the URI that will be used for request the nudge server.
     *
     * @param propertiesMap this map must contains the
     * @param action
     * @return
     */
    protected HttpMethod constructHttpMethod(final Map<String, Object> propertiesMap, final ActionType action) {

        // validate
        // url ends with / for instance
        //appCode no ClassCastException, ActionType
        // if no granularity, put a default one ??

        String urlNudgeApi = (String) propertiesMap.get("urlApi");
        String applicationCode = (String) propertiesMap.get("applicationCode");
        long start = (Long) propertiesMap.get("start");
        long end = (Long) propertiesMap.get("end");
        String login = (String) propertiesMap.get("login");
        String password = (String) propertiesMap.get("password");
        GranularityType granularity = (GranularityType) propertiesMap.get("granularity");

        // construct the uri
        StringBuilder uri = new StringBuilder();
        uri.append(urlNudgeApi).append(applicationCode)
                .append("/").append(action.getValue())
                .append("?start=").append(start)
                .append("&end=").append(end);

        // special case
        if (ActionType.TRANSACTION_MEASURES.equals(action)) {
            if (granularity != null) {
                uri.append("&granularity=").append(granularity.getValue());
            }
        }

        PostMethod method = new PostMethod(uri.toString());
        // add login parameters
        method.addParameter("nudge_username", login);
        method.addParameter("nudge_password", password);

        return method;
    }


    protected BufferedReader requestNudge(HttpMethod httpMethod) throws IOException {

        /*
        if (StringUtils.isEmpty(uriToRequest) || StringUtils.isEmpty(nudgeUser) || StringUtils.isEmpty(nudgePwd)) {
            LOG.error("Impossible to request the nudge server, the uri is empty");
            throw new IllegalArgumentException("The uri to request the nudge server, the login or the password is empty");
        }
          */

        HttpClient httpClient = new HttpClient();

        try {
            httpClient.executeMethod(httpMethod);
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }


        LOG.debug("Nudge request statusCode={}", httpMethod.getStatusCode());
        if (httpMethod.getStatusCode() != 200) {
            LOG.error("Error ...");
            throw new IOException("Error request nudge server");
        }
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(httpMethod.getResponseBodyAsStream()));
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        return reader;
    }


    public HttpClient getHttpClient() {
        return httpClient;
    }

    public void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

}
